Visualización de datos

Visualizar datos en R principalmente con ggplot

Visualización

Para entender patrones y relaciones

Para comunicar resultados de forma clara

Para detectar errores o valores atípicos

Porque una imagen resume más que una tabla

Matetja et al

Colores

Colores… https://www.fabiocrameri.ch/colourmaps/

https://github.com/jbgb13/peRReo https://github.com/BlakeRMills/MetBrewer scale_fill_manual (values=c(“#72874EFF”, “#FED789FF”))

En R, desde gráficos muy simples

hasta muy complejos

quién habla con quién en “The Office” Código

R base versus ggplot

plot(penguins$bill_length_mm, 
     penguins$bill_depth_mm)

ggplot(penguins, 
       aes(x = bill_length_mm, 
           y = bill_depth_mm)) +
  geom_point()

Sin adornos

ggplot(data = penguins, aes(x = bill_length_mm, y = bill_depth_mm)) + geom_point()

Con muchos adornos

Bases de ggplot

ggplot = Grammar of Graphics (gg) Separa cada componente de un gráfico en componentes individuales, creando distintas capas. Así tenemos resultados más flexibles y personalizables.

  • Data
  • Aesthetics (x, y)
  • Geometries (points, lines, boxplots)
  • Scales (eg. colores)
  • Facets (subplots)
  • Statistics (show means, counts, and other statistical summaries of data)
  • Coordinates
  • Theme (apariencia general del gráfico)

Layers inside ggplot

Ejemplo de capas

Hertz & McNeill 2024

Aesthetics

  • x, y
  • colour: color de los geoms (CONTORNO)
  • fill: el color de dentro de los geoms (RELLENO)
  • group: a qué grupo pertenece un geom
  • shape: la forma de los puntos
  • linetype: tipo de linea (solid, dashed, etc)
  • size: escalar el tamaño
  • alpha: transparencia

RforEcology.com

Geometries

Categórico

  • geom_bar(): bar charts for categorical x axis
  • geom_boxplot(): box and whiskers plot for categorical variables
  • geom_violin(): distribution kernel of data dispersion

Continuo

  • geom_histogram(): histogram for continuous x axis
  • geom_point(): scatterplot
  • geom_line(): lines connecting points by increasing value of x
  • geom_path(): lines connecting points in sequence of appearance

Scales

Scales se puede modificar el tipo de variable, transformarla, tamaño, color, nombre etc.

Facets

  • facet_wrap()
  • facet_grid()

facet_wrap(~ variable) | Divide el gráfico en varios paneles según una sola variable. Coloca los paneles en una cuadrícula flexible (se “envuelven” automáticamente).

facet_grid(fila ~ columna) | Divide los gráficos según dos variables: una define las filas y otra las columnas.

Themes

geeksforgeeks

Empecemos a visualizar

Cosas importantes!

  • Primero pensar qué queremos visualizar (dibujo?)
  • El orden donde ponemos los argumentos
  • Si van dentro de paréntesis o no
  • dónde va la base de datos a la que hacemos referencia

LA CAPA ‘DATA’

Volvemos con los pingüinos. ggplot = base de datos

ggplot(penguins)

LA CAPA ‘AESTHETICS’

ggplot = base de datos + aesthetics

ggplot(penguins, 
       aes(x = flipper_length_mm))

La base de datos puede antes con el pipe de dplyr ggplot = base de datos + aesthetics

penguins %>%
  ggplot(aes(x = flipper_length_mm))

LA CAPA ‘GEOMETRIC’

ggplot + base de datos + aesthetics + geoms

ggplot(penguins, 
       aes(x = flipper_length_mm)) + 
  geom_histogram() 

ggplot + base de datos + aesthetics + geoms aesthetics puede ir en ggplot o en geoms

ggplot(penguins) + 
  geom_histogram(aes(x = flipper_length_mm)) 

Gráfico de densidad

ggplot(penguins, 
       aes(x = flipper_length_mm)) + 
  geom_density(bw=1)
penguins %>%
ggplot (aes(x = flipper_length_mm, fill=species)) + 
  geom_density(bw=1)

Gráfico de Barras

Geom_bar por defecto nos cuenta el numero de datos

penguins %>%
  ggplot (aes(x=species)) +
  geom_bar() 

Gráfico de Barras

Para que nos haga la suma, necesitamos “identity”

penguins %>%
ggplot(aes(x=species, y=bill_length_mm)) +
    geom_bar(stat="identity")

Para que haga la media, le decimos que la estadística (stat) es un “summary” con la función “mean”

penguins %>%
ggplot(aes(x = species, y = bill_length_mm)) +
    geom_bar(stat="summary", fun = "mean")

CAMBIAMOS LOS COLORES

Queremos la especie en distintos colores.

Dentro de aesthetics añadimos el argumento fill para cambiar el “relleno” segun el grupo que indiquemos. Nos dará un color ya establecido por ggplot.

penguins %>%
ggplot(aes(x=species, y=bill_length_mm, fill=species)) +
    geom_bar(stat="identity")

¿Qué pasa si modificamos “color”? … mal

penguins %>%
ggplot(aes(x=species, y=bill_length_mm, color=species)) +
    geom_bar(stat="identity")

tip: sin leyenda guides (fill=FALSE)

penguins %>%
ggplot(aes(x=species, y=bill_length_mm, fill=species)) +
    geom_bar(stat="identity")+
    guides(fill=FALSE)

Añadimos el labs y theme

penguins %>%
ggplot(aes(x=species, y=bill_length_mm, fill=species)) +
    geom_bar(stat="identity")+
    guides(fill=FALSE) +
    labs(title = "Longitud del pico en mm", 
       subtitle = "Suma por especie",
       x = "Especie de pingüino",
       y = "Longitud del pico") + theme_minimal()

Incluímos una variable más

Añadiendo en “fill” el sexo del pingüino.

penguins %>%
  ggplot(aes(x=species, y=bill_length_mm, fill=sex)) +
  geom_bar(stat="identity")

Quitamos NAs y añadimos position_dodge() para visualizarlos uno al lado del otro

penguins %>%
  filter(!is.na(sex)) %>%
  ggplot(aes(x=species, y=bill_length_mm, fill=sex)) +
    geom_bar(stat="identity", position=position_dodge()) 

Colores personalizados

penguins %>%
  filter (!is.na(sex)) %>%
  ggplot (aes(x=species, y=bill_length_mm, fill=sex)) +
  geom_bar (stat="identity", position=position_dodge()) +
  scale_fill_manual (values=c("#72874EFF", "#FED789FF")) + 
  theme_minimal () 

Boxplot

penguins %>% 
  ggplot (aes(x = island, y = bill_length_mm)) + 
  geom_boxplot ()
penguins %>% 
  ggplot (aes(x = island, y = bill_length_mm, fill=island)) + 
  geom_boxplot ()
penguins %>% 
  ggplot (aes(x = island, y = bill_length_mm, color=island)) + 
  geom_boxplot ()

Cuidado con los boxplots!

Seven distributions of data, shown as raw data points (of strip-plots), as box plots, and as violin plots

Fuente

Violin plot

violin_plot <- penguins %>% 
  ggplot (aes(x = island, y = bill_length_mm, fill = island)) + 
  geom_jitter (size=3, alpha=0.1, fill="grey") +
  geom_violin (alpha=0.8) +  guides (fill= FALSE) +
  scale_fill_manual (values=c("#72874EFF", "#FED789FF", "#023743FF")) +
  theme_light() 

violin_plot
#ggsave("images/violin_plot.png", violin_plot, width = 20, height = 20, units = "cm", scale = .5)

Guardar plots con ggsave

  • ggsave(“images/violin_plot.png”, violin_plot, width = 20, height = 20, units = “cm”, scale = .5)

  • ggsave nos permite guardar en “eps”, “ps”, “tex” (pictex), “pdf”, “jpeg”, “tiff”, “png”, “bmp”, “svg” or “wmf”

Violines

Datos continuos

Miramos las correlaciones entre nuestras variables de manera gráfica

library(GGally)

penguins %>% 
  ggpairs(columns = 3:5, ggplot2::aes(colour=species)) 

Scatterplots

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm)) + 
  geom_point() 

Cuidado con el argumento color y fill

Hay que estar atentos dónde están colocados Si van dentro de aes() tiene que ser una variable y no un color per se.

penguins %>% 
  ggplot () + 
  geom_point(aes(x = flipper_length_mm, y = bill_length_mm, color="blue")) 

Aquí bien

Fuera de aesthetics sí puede ser un color

penguins %>% 
  ggplot () + 
  geom_point(aes(x = flipper_length_mm, y = bill_length_mm), color="blue") 

Color

Dentro de aesthetics tiene que ser una variable de nuestra bbdd

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = island)) + 
  geom_point() + theme_light() 

LA CAPA ‘SCALES’

Color categórico

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = island)) + 
  geom_point() + 
  scale_colour_manual(values=c("#72874EFF", "#FED789FF", "#023743FF")) +
  theme_light() 

Color continuo

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = bill_length_mm)) + 
  geom_point() + theme_light() 

Gradientes de color

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = bill_length_mm)) + 
  geom_point() +
  scale_color_gradient(low="#00AFBB", high="#E7B800")+
  theme_light() 

Colores continuos de paletas (viridis)

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = bill_length_mm)) + 
  geom_point() +
  scale_color_viridis_c(option = "plasma") + 
  theme_light() 

Colores continuos de paletas (RColorBrewer)

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = bill_length_mm)) + 
  geom_point() +
  scale_color_distiller(palette = "Spectral") +  # otras: "RdYlBu", "YlGnBu", "PuOr", etc.
  theme_light() 

Cambiar el tamaño del punto

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, size = body_mass_g, color=body_mass_g)) +
  scale_color_gradient(low="orange",high="black")+
  geom_point(alpha=0.8) + theme_light() 

Otras visualizaciones de los mismos datos

Densidades en dos dimensiones

# Show the contour only
penguins %>% 
ggplot (aes(x = flipper_length_mm, y = bill_length_mm))+
  geom_density_2d(color="black") + theme_minimal ()

LA CAPA STATISTICS

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm)) + 
  geom_point() + geom_smooth()
# Method = "loess"

Modelos lineales

Podemos visualizar cómo quedaría un modelo lineal

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm)) + 
  geom_point() + theme_light() + geom_smooth(method = "lm")

Modelos lineales con interacción

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = island)) +
  geom_point () +
  scale_colour_manual (values=c("lightblue", "purple", "pink")) +
  theme_light() + geom_smooth(method = "lm")

LA CAPA FACETS

Dividir por especie

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = island)) + 
  scale_colour_manual (values=c("lightblue", "purple", "pink")) +
  geom_point() + theme_light() +  facet_wrap(~species, scales = "free")

Dividir por especie y por isla

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = island)) + 
  scale_colour_manual (values=c("lightblue", "purple", "pink")) +
  geom_point() + theme_light() +  facet_wrap(species~island, scales = "free")

facet grid por pares

penguins %>% 
  ggplot (aes(x = flipper_length_mm, y = bill_length_mm, colour = island)) + 
  scale_colour_manual (values=c("lightblue", "purple", "pink")) +
  geom_point() + theme_light() +  facet_grid(species~island, scales = "free")

Plotear texto

geom_text()

ggplot(penguins, aes(x = flipper_length_mm, y = bill_length_mm)) +
  geom_text(aes(label = 'pingus')) +
  theme_minimal()
ggplot (penguins, aes(x = flipper_length_mm, y = bill_length_mm)) +
  geom_text (aes(label = species, color = species)) +
  theme_minimal() 

Patchwork

Guardamos los ggplots como objetos y los “sumamos”

library(patchwork)
p1 <- ggplot(penguins, aes(x = flipper_length_mm, y = bill_length_mm)) +
  geom_text(aes(label = 'pingus')) +
  theme_minimal()
p2 <- ggplot (penguins, aes(x = flipper_length_mm, y = bill_length_mm)) +
  geom_text (aes(label = species, color = species)) +
  theme_minimal() 

p1 + p2

o “dividimos”

p1 / p2

Mapas I

Mapa del crecimiento urbano en Valencia Código

Mapas II

Apicultores en Alemania Código

Nuestros datos georeferenciados

library(rgbif)
library(ggplot2)
library(rnaturalearth)
library(sf)

datos <- occ_search(scientificName = "Lynx pardinus", limit = 100)
df <- datos$data
world <- ne_countries(scale = "medium", returnclass = "sf")

# Plot
ggplot() +
  geom_sf(data = world, fill = "grey90", color = "grey30") +
  geom_point(data = df, aes(x = decimalLongitude, y = decimalLatitude),
             color = "darkred", size = 2, alpha = 0.7) +
  coord_sf() +
  theme_minimal()
# Basic map
spain <- ne_countries(country=c("spain", "portugal"))
ggplot() +
  geom_sf(data = spain, fill = "grey99", color = "grey30") +
  geom_point(data = df, aes(x = decimalLongitude, y = decimalLatitude),
             color = "darkgreen", size = 2, alpha = 0.7) +
  coord_sf() +
  theme_minimal()

Mapa plantas

library(FloraIberica)
map_distribution(genus = "Lavandula", species = "stoechas", size = 0.9)

Visualizaciones geniales (ya no solo con r)

Valentina de Filippo

gg cosas

example ggimaga R logo

example ggimage R logo

gganimate

ggDNAvis is an R package that uses ggplot2 to visualise genetic data.

library(ggDNAvis)
sequence <- paste(c(rep("GGC", 72), rep("GGAGGAGGCGGC", 15)), collapse = "")

visualise_single_sequence(
    sequence = sequence,
    sequence_colours = sequence_colour_palettes$bright_pale,
    background_colour = "white",
    line_wrapping = 60,
    spacing = 1,
    margin = 0.5,
    sequence_text_colour = "black",
    sequence_text_size = 1,
    index_annotation_colour = "darkred",
    index_annotation_size = 1,
    index_annotation_interval = 1,
    index_annotation_vertical_position = 1/3,
    outline_colour = "black",
    outline_linewidth = .4,
    outline_join = "mitre",
    return = TRUE,
    render_device = ragg::agg_png,
    pixels_per_base = 100
)

code ggDNAvis

Bibliografía

Valentina de Filippo Tips tables

ggbasics

book

grphs

geels

Ejercicios

  1. Haz el violin_plot de antes pero los jitter son del color de la isla.
penguins %>% 
  ggplot (aes(x = island, y = bill_length_mm, fill = island)) + 
  geom_jitter (size=3, alpha=0.1, fill="grey") +
  geom_violin(alpha=0.8) +  guides (fill= FALSE)+
  scale_fill_manual(values=c("#72874EFF", "#FED789FF", "#023743FF")) +
  theme_light() + theme(rect = element_rect(fill = "transparent"))
  1. Lee la base de datos de “flores.csv”

Haz un scatterplot comparando biomasa y cobertura, señalando las diferencias entre sequia o lluvia.

Haz un boxplot por los dos tipos de sequía y la cobertura de árboles

Resolvemos los ejercicios

penguins %>% 
  ggplot (aes(x = island, y = bill_length_mm, fill = island)) + 
  geom_jitter (aes(color=island), size=2, alpha=0.9) +
  scale_color_manual(values=c("#72874EFF", "#FED789FF", "#023743FF")) +
  geom_violin (alpha=0.8) +  guides (fill= FALSE)+
  scale_fill_manual(values=c("#72874EFF", "#FED789FF", "#023743FF")) +
  theme_light() + theme(rect = element_rect(fill = "transparent"))
library(here)
cobertura <- read.csv(here("data/cobertura.csv"))
head(cobertura)
  X  biomasa cobertura sequia
1 1 44.99793  18.55938   seco
2 2 24.05575  24.14701   seco
3 3 62.48798  68.89674   seco
4 4 47.19165  30.01684   seco
5 5 52.97670  31.25460   seco
6 6 54.23581  38.79990   seco
ggplot(cobertura) +
  geom_point(aes(x=biomasa, y=cobertura, color=sequia))

ggplot(cobertura) +
  geom_boxplot(aes(x=biomasa, y =cobertura, group=sequia))